#include "RoComponent.h"
#include "RoAbstractModule.h"
#include "RoModule.h"


RoModule::RoModule(QObject * parent, bool logTraffic):
    super(parent),
    transport(new QTcpSocket(this)),
    _stream(new RoXmlStream(this, transport, RoXmlStream::LogTraffic * logTraffic))
{
    // сначала открыть поток, потом сообщить об установлении соединения
    {
        connect(transport, SIGNAL( connected() ),
                this, SLOT( openXmlStream() ));
    }

    connect(transport, SIGNAL( disconnected() ),
            this, SIGNAL( disconnected() ));
    connect(transport, SIGNAL( error(QAbstractSocket::SocketError) ),
            this, SIGNAL( error(QAbstractSocket::SocketError) ));

    connect(_stream, SIGNAL( stanza(RoStanza) ),
             this, SLOT( recieve_stanza(RoStanza) ));
}


RoModule::~RoModule()
{
    closeXmlStream();
}


bool RoModule::connectToNetwork(const QString & hostName, quint16 port)
{
    transport->connectToHost(hostName, port);

    // а после TCP-соединения по сигналу connected() будет открыт XML-поток

    return true;
}


void RoModule::disconnectFromNetwork()
{
    closeXmlStream();
    transport->disconnectFromHost();
}


bool RoModule::isConnected() const
{
    return transport->state() == QAbstractSocket::ConnectedState;
}


RoStanzaId RoModule::sendStanza(RoStanza stanza)
{
    _stream->writeStanza(stanza);
    return stanza.id();
}


void RoModule::openXmlStream()
{
    _stream->openStream();

    // если всё хорошо, то поток действительно открылся
    if ( _stream->isOpen() )
    {
        announceComponents();

        emit connected();
    }
}


void RoModule::closeXmlStream()
{
    foreach ( RoAbstractComponent * component, findComponents() )
    {
        _stream->writeStanza( RoInfoStanza("presence")
                              .setAttribute("from", component->name())
                              .setBodyAttribute("status", "unavailable") );
    }

    _stream->closeStream();
}


void RoModule::announceComponents()
{
    foreach ( RoAbstractComponent * component, findComponents() )
    {
        _stream->writeStanza( RoInfoStanza("presence")
                              .setAttribute("from", component->name())
                              .setBodyAttribute("status", "available") );
    }
}


void RoModule::recieve_stanza(RoStanza stanza)
{
    recieve_own_stanza(stanza);
}
